package main

import (
	"fmt"
)

// 抽象类，制作饮料，包裹一个模板，全部实现步骤

type Beverage interface {

	// BoilWater 煮开水
	BoilWater()

	// Brew 冲泡
	Brew()

	// PourInCup 倒入杯中
	PourInCup()

	// AddThings 添加佐料
	AddThings()
}

// 封装一套流程模板基类，让具体地制作流程继承且实现
type template struct {
	b Beverage
}

func (t *template) MakeBeverage() {
	if t == nil {
		return
	}
	t.b.BoilWater()
	t.b.Brew()
	t.b.PourInCup()
	t.b.AddThings()
}

// 具体地制作饮料的流程

type MakeCoffee struct {
	template //继承模板
}

// 煮开水

func (mc *MakeCoffee) BoilWater() {
	fmt.Println("将水煮到100摄氏度")
}

func (mc *MakeCoffee) Brew() {
	fmt.Println("用水冲咖啡豆..")
}

func (mc *MakeCoffee) PourInCup() {
	fmt.Println("将冲好的咖啡倒入陶瓷杯中...")
}

func (mc *MakeCoffee) AddThings() {
	fmt.Println("添加佐料..")
}

func NewMakeCoffee() *MakeCoffee {
	makeCoffee := new(MakeCoffee)

	//b 是 Beverage 是MakeCoffee 地接口 这里需要给接口管理  让b指向 具体地子类
	// 来触发b地全部方法地多态特性
	makeCoffee.b = makeCoffee
	return makeCoffee
}

func main() {
	//制作一杯咖啡
	makeCoffee := NewMakeCoffee()
	// 调用模板方法
	makeCoffee.MakeBeverage()
}
